package com.xuanyuan.service.impl;

import cn.hutool.core.io.IoUtil;
import com.xuanyuan.domain.AjaxResult;
import com.xuanyuan.entity.File;
import com.xuanyuan.exception.BusinessException;
import com.xuanyuan.mapper.FileMapper;
import com.xuanyuan.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class FileServiceImpl implements FileService {
    @Autowired
    private FileMapper fileMapper;

    @Value("${fileLocation}")
    private String fileLocation;


    public void saveFile(File file) {
        MultipartFile multipartFile = file.getFile();
        if (multipartFile == null || multipartFile.isEmpty())
            throw new BusinessException(-1, "文件为空,请选择你的文件上传");
        if (multipartFile.getOriginalFilename().length() > 250)
            throw new BusinessException(-1, "文件名字过长,请重新选择你的文件上传");
        try {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
            String dateSrt = formatter.format(new Date());
            String fileName = dateSrt + "_" + multipartFile.getOriginalFilename();
            // 获得 classpath 的绝对路径
            String realPath = ResourceUtils.getURL("classpath:static").getPath() + fileLocation;
            java.io.File newFile = new java.io.File(realPath);
            // 如果文件夹不存在、则新建
            if (!newFile.exists()) newFile.mkdirs();
            newFile = new java.io.File(newFile, fileName);
            //写出文件
            multipartFile.transferTo(newFile);
            //入库
            file.setFileName(fileName);
            file.setFilePath(fileLocation + fileName);
            log.info("[文件保存完成:]{}", newFile);
        } catch (Exception e) {
            throw new BusinessException(-1, "文件保存失败:" + e);
        }
    }

    @Override
    public void downloadFile(String fileName, HttpServletResponse response) {
        try {
            // 获得待下载文件所在文件夹的绝对路径
            String realPath = ResourceUtils.getURL("classpath:static").getPath() + fileLocation;
            // 获得文件输入流
            FileInputStream inputStream = new FileInputStream(new java.io.File(realPath, fileName));
            // 设置utf8编码
            response.setCharacterEncoding("UTF-8");
            // 设置响应头、以附件形式打开文件
            response.setHeader("content-disposition", "attachment; fileName=" + URLEncoder.encode(fileName, "UTF-8"));
            ServletOutputStream outputStream = response.getOutputStream();
            //复制io流
            IoUtil.copy(inputStream, outputStream, IoUtil.DEFAULT_BUFFER_SIZE);
            log.info("[文件下载完成:]{}", fileName);
            outputStream.close();
            inputStream.close();
        } catch (Exception e) {
            throw new BusinessException(-1, "文件下载失败:" + e.getMessage());
        }
    }

    public void removeFileByName(String fileName) {
        try {
            String realPath = ResourceUtils.getURL("classpath:static").getPath() + fileLocation;
            java.io.File file = new java.io.File(realPath, fileName);
            if (file.delete()) {
                log.info("[删除文件成功]{}", file);
            } else {
                log.info("[删除文件失败]{}", file);
            }
        } catch (Exception e) {
            log.error("[删除文件异常] {e}", e);
        }
    }

    public void removeFileById(String id) {
        try {
            File file = fileMapper.selectFileById(id);
            removeFileByName(file.getFileName());
        } catch (Exception e) {
            log.error("[通过 id 删除文件异常] {e}", e);
        }
    }

    public void removeFileByIds(String[] ids) {
        try {
            Arrays.stream(ids).forEach(id -> {
                File file = fileMapper.selectFileById(id);
                if (file != null) removeFileByName(file.getFileName());
            });
        } catch (Exception e) {
            log.error("[通过 ids 批量删除文件异常] {e}", e);
        }
    }

    @Override
    public File selectFileByName(String fileName) {
        return fileMapper.selectFileByName(fileName);
    }

    @Override
    public File selectFileById(String id) {
        return fileMapper.selectFileById(id);
    }

    @Override
    public List<File> selectFileList(File file) {
        return fileMapper.selectFileList(file);
    }

    @Override
    public AjaxResult insertFile(File file) {
        saveFile(file);
        return AjaxResult.toAjax(fileMapper.insertFile(file));
    }

    @Override
    public AjaxResult updateFile(File file) {
        //删除旧文件
        removeFileById(String.valueOf(file.getId()));
        //删除新文件
        saveFile(file);
        return AjaxResult.toAjax(fileMapper.updateFile(file));
    }

    @Override
    public Integer deleteFileByIds(String[] ids) {
        //批量删除旧文件
        removeFileByIds(ids);
        return fileMapper.deleteFileByIds(ids);
    }
}
